//
// Created by Administrator on 2021/10/21.
//

#include "Shader.h"

/**
 * 获得shder对象，使用默认shder
 */
Shader::Shader() {
    // 读取文件
    String vsSource = FileUtil::readStrFromFile(SHADER_FOLDER + DEFAULT_SHADER + ".vs");
    String fsSource = FileUtil::readStrFromFile(SHADER_FOLDER + DEFAULT_SHADER + ".fs");

    /**
     * 编译
     */
    this->program = compileProgram(vsSource, fsSource);
    name = DEFAULT_SHADER;
}

/**
 * 获得shader对象并编译
 * @param vsFilePath
 * @param fsFilePath
 */
Shader::Shader(String _name, String vsFilePath, String fsFilePath) {
    // 读取文件
    String vsSource = FileUtil::readStrFromFile(vsFilePath);
    String fsSource = FileUtil::readStrFromFile(fsFilePath);

    // 编译
    this->program = compileProgram(vsSource, fsSource);
    name = _name;
}

/**
* 编译Shder源码
*/
GLuint Shader::compileProgram(String vertexShaderSource, String fragmentShaderSource) {
    const char* vertexShaderSource_cstr = vertexShaderSource.c_str();
    const char* fragmentShaderSource_cstr = fragmentShaderSource.c_str();
    //标识编译和链接是否成功
    int logLength = 512;
    int success;
    char infoLog[logLength];
    unsigned  int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource_cstr, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if(!success){
        glGetShaderInfoLog(vertexShader, logLength, NULL, infoLog);
        log_error("vertexShader-compile failed.%s", infoLog);
        MAssert::check(success, "vertexShader-compile failed.");
    }

    unsigned  int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource_cstr, NULL);
    glCompileShader(fragmentShader);
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success){
        glGetShaderInfoLog(fragmentShader, logLength, NULL, infoLog);
        log_error("fragmentShader-compile failed.%s", infoLog);
        MAssert::check(success, "fragmentShader-compile failed.");
    }

    unsigned int program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);
    glGetProgramiv(program, GL_LINK_STATUS, &success);
    if(!success){
        glGetProgramInfoLog(program, logLength, NULL, infoLog);
        log_error("link-program failed.%s", infoLog);
        MAssert::check(success, "link-program failed. failed.");
    }

    glDetachShader(program, vertexShader);
    glDetachShader(program, fragmentShader);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    return program;
}

bool Shader::check() {
    return program > 0;
}
/**
 * 返回当前shader的program
 * @return
 */
unsigned int Shader::getProgram() const {
    return program;
}

/**
* 返回名称
* @return 名称
*/
const String &Shader::getName() const {
    return name;
}


void Shader::setUniform(const char *uniformVar, const float v) const {
    glUniform1f(glGetUniformLocation(program, uniformVar), v);
}


/**
  * 设置单个int值
  * @param uniformVar 变量
  * @param v 值
  */
void Shader::setUniform(const char *uniformVar, const int v) const {
    glUniform1i(glGetUniformLocation(program, uniformVar), v);
}

/**
 * 设置颜色值
 * @param uniformVar 变量
 * @param m 值
 */
void Shader::setUniform(const char *uniformVar, const Color &c) const {
    glUniform4f(glGetUniformLocation(program, uniformVar), c.r, c.g, c.b, c.a);
}

/**
 * 设置矩阵值
 * @param uniformVar 变量
 * @param m 值
 */
void Shader::setUniform(const char *uniformVar, const Matrix4x4 &m) const {
    //vector全部转到数组
    float mt[m.data.size()];
    CP_VECTOR_TO_ARRAY(mt, m.data);
    glUniformMatrix4fv(glGetUniformLocation(program, uniformVar), 1, false, mt);
}

